package svc.elib.analysis;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;

import svc.elib.db.Database;
import svc.elib.socnet.ConnectedComponents;
import svc.elib.socnet.EvolutionarySnapshots;
import svc.elib.socnet.Net;
import svc.elib.socnet.SocConstructor;
import svc.elib.socnet.TrivialComponents;

/**
 * Evolution of collaboration network
 * 
 * @author svc
 * @date 10.8.2012
 */
public class NetworkEvolution {
	
	private Net[] snaps;
	private Net net;
	private int startYear;
	
	public NetworkEvolution(Net net) {
		this.net = net;
		EvolutionarySnapshots es = new EvolutionarySnapshots(net);
		startYear = es.getStartYear();
		snaps = es.getSnapshots();
	}
	
	public void observe(String outFile) 
		throws IOException
	{
		PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
		String header = "year,#nodes,#links,density,#isolated,#trivialAuthors,avgdeg,#comp,avgCompSize,avgCompDensity,diameter,sw,cc,";
		header = header + "t_#comp,t_avgcompsize,t_avgCompDensity,t_diameter,t_sw,t_cc";
		pw.println("# File generated by svc.elib.analysis.NetworkEvolution");
		DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		Date date = new Date();
		pw.println("# Date " + dateFormat.format(date));
		pw.println(header);
		
		int numSnaps = snaps.length;
		for (int i = 0; i < numSnaps; i++) {
			Net snap = snaps[i];
			int year = startYear + i;
			
			snap.degreeStatistics();
			int numNodes = snap.getNumNodes();
			int numLinks = snap.getNumLinks();
			double density = snap.getDensity();
			int numIsolated = snap.getNumIsolated();
			double avgDegree = snap.getAverageDegree();
			
			ConnectedComponents components = new ConnectedComponents(snap);
			components.resolveComponents();
			int numComponents = components.getNumComponents();
			double avgCompSize = components.avgComponentSize();
			double avgCompDensity = components.avgComponentDensity();
			
			double diameter = snap.getDiameter();
			double sw = snap.getSW2();
			double cc = snap.getCC();
			
			TrivialComponents tc = new TrivialComponents(snap);
			tc.determine();
			tc.filter();
			int numAuthorsInTrivialComponents = tc.getNumAuthorsInTrivialComponents();
			components = new ConnectedComponents(snap);
			components.resolveComponents();
			
			int t_numComponents = components.getNumComponents();
			double t_avgCompSize = components.avgComponentSize();
			double t_avgCompDensity = components.avgComponentDensity();
			
			double t_diameter = snap.getDiameter();
			double t_sw = snap.getSW2();
			double t_cc = snap.getCC();
			
			
			StringBuilder sb = new StringBuilder();
			sb.append(year).append(",")
			  .append(numNodes).append(",")
			  .append(numLinks).append(",")
			  .append(density).append(",")
			  .append(numIsolated).append(",")
			  .append(numAuthorsInTrivialComponents).append(",")
			  .append(avgDegree).append(",")
			  .append(numComponents).append(",")
			  .append(avgCompSize).append(",")
			  .append(avgCompDensity).append(",")
			  .append(diameter).append(",")
			  .append(sw).append(",")
			  .append(cc).append(",")
			  .append(t_numComponents).append(",")
			  .append(t_avgCompSize).append(",")
			  .append(t_avgCompDensity).append(",")
			  .append(t_diameter).append(",")
			  .append(t_sw).append(",")
			  .append(t_cc);
			
			pw.println(sb.toString());
			System.out.println(sb.toString());
		}
		
		pw.close();
	}
	
	public void observe2(String outFile) 
		throws IOException
	{
		PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
		
		int numSnaps = snaps.length;
		pw.println("year,nodeLinkRatio,fIsolated,nonTrivialComps,trivVolume,avgCompSize,cc");
		for (int i = 0; i < numSnaps; i++) {
			Net snap = snaps[i];
			int year = startYear + i;
			
			ConnectedComponents components = new ConnectedComponents(snap);
			components.resolveComponents();
			
			int numNodes = snap.getNumNodes();
			int numLinks = snap.getNumLinks();			
			int numComps = components.getNumComponents();
			int numIsolated = snap.getNumIsolated();
			TrivialComponents tc = new TrivialComponents(snap);
			tc.determine();
			tc.filter();
			
			int numAuthorsInTrivialComponents = tc.getNumAuthorsInTrivialComponents();
			
			components = new ConnectedComponents(snap);
			components.resolveComponents();
			
			int t_numComponents = components.getNumComponents();
			
			double nonTrivialComps = (double) t_numComponents / (double) numComps;
			double fIsolated = (double) numIsolated / (double) numNodes;
			double trivVolume = (double) numAuthorsInTrivialComponents / (double) (numNodes - numIsolated);
			double nodeLinkRatio = (double) numLinks / (double) (numNodes - numIsolated);
			double avgCompSize = components.avgComponentSize();
			double cc = snap.getCC();
			
			pw.println(year + "," + nodeLinkRatio + "," + fIsolated + "," + nonTrivialComps + "," + trivVolume + "," + avgCompSize + "," + cc);
		}
		
		pw.close();
	}
	
	public void observe3() {
		TrivialComponents tc = new TrivialComponents(net);
		tc.determine();
		tc.filter();
		
		EvolutionarySnapshots es = new EvolutionarySnapshots(net);
		startYear = es.getStartYear();
		snaps = es.getSnapshots();
		
		int numSnaps = snaps.length;
		for (int i = 0; i < numSnaps; i++) {
			Net snap = snaps[i];
			int year = startYear + i;
			
			ConnectedComponents components = new ConnectedComponents(snap);
			components.resolveComponents();
			
			double avgCompSize = components.avgComponentSize();
			double cc = snap.getCC();
			
			System.out.println(year + ", " + avgCompSize + ", " + cc);
		}
	}
	
	public static void main(String[] args) 
		throws IOException
	{
		Database db = new Database("eLibData.csv", 1932, 2011);
		System.out.println(db.info());
		SocConstructor soc = new SocConstructor(db);
		Net net = soc.getNet();
		net.printInfo();
		
		NetworkEvolution ne = new NetworkEvolution(net);
		//ne.observe("results/eLibSocNetEvol.csv");
		//ne.observe2("results/eLibSocNet_CompParam_evol.csv");
		
		ne.observe3();
		
		/*
		ConnectedComponents cn = new ConnectedComponents(net);
		cn.resolveComponents();
		LinkedList<Net> comps = cn.getComponents();
		Net largestComponent = comps.get(0);
		ne = new NetworkEvolution(largestComponent);
		ne.observe("results/LargestComponentEvol.csv");
		*/
	}
}
